﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;

namespace Dtf.Core.Utilities
{
    /// <summary>
    /// From Mita
    /// </summary>
    public class ScreenCapture
    {
        public static Image GetImage(int x, int y, int width, int height)
        {
            Image img;
            IntPtr displayDC = IntPtr.Zero;
            IntPtr compatibleDC = IntPtr.Zero;
            IntPtr bitmap = IntPtr.Zero;
            if (width <= 0)
            {
                throw new ArgumentOutOfRangeException("width", width, "RectangleMustBeNonEmpty");
            }
            if (height <= 0)
            {
                throw new ArgumentOutOfRangeException("height", height, "RectangleMustBeNonEmpty");
            }
            try
            {
                displayDC = NativeMethods.CreateDC("DISPLAY", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
                if (displayDC == IntPtr.Zero)
                {
                    throw new Exception("UnableToGetDC");
                }
                compatibleDC = NativeMethods.CreateCompatibleDC(displayDC);
                if (compatibleDC == IntPtr.Zero)
                {
                    throw new Exception("UnableToCreateDC");
                }
                bitmap = NativeMethods.CreateCompatibleBitmap(displayDC, width, height);
                if (bitmap == IntPtr.Zero)
                {
                    throw new Exception("UnableToCreateBitmap");
                }
                if (NativeMethods.SelectObject(compatibleDC, bitmap) == IntPtr.Zero)
                {
                    throw new Exception("CannotSelectBitmapIntoDC");
                }
                if (NativeMethods.BitBlt(compatibleDC, 0, 0, width, height, displayDC, x, y, 0xcc0020 | 0x40000000) == 0)
                {
                    throw new Exception("BitBlitFailed");
                }
                img = Image.FromHbitmap(bitmap);
            }
            finally
            {
                NativeMethods.DeleteDC(displayDC);
                NativeMethods.DeleteDC(compatibleDC);
                NativeMethods.DeleteObject(bitmap);
            }
            return img;

        }

        internal class NativeMethods
        {
            [DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
            internal static extern int BitBlt(IntPtr destDC, int xDest, int yDest, int width, int height, IntPtr sourceDC, int xSource, int ySource, uint rasterOperation);

            [DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
            internal static extern IntPtr CreateCompatibleBitmap(IntPtr dc, int width, int height);



            [DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
            internal static extern IntPtr CreateCompatibleDC(IntPtr dc);



            [DllImport("gdi32.dll", EntryPoint = "CreateDCW", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
            internal static extern IntPtr CreateDC(string driver, IntPtr device, IntPtr output, IntPtr devMode);

            [DllImport("gdi32.dll", ExactSpelling = true)]
            internal static extern int DeleteDC(IntPtr dc);

            [DllImport("gdi32.dll", ExactSpelling = true)]
            internal static extern int DeleteObject(IntPtr gdiObject);

            [DllImport("gdi32.dll", SetLastError = true, ExactSpelling = true)]
            internal static extern IntPtr SelectObject(IntPtr dc, IntPtr gdi);


        }

 

    }
}
